<template>
  <div class="main-app">
    <main class="app-container">
      <!-- 子应用显示frame -->
      <iframe
        v-for="app in registeredApps.values()"
        :key="app.name"
        :id="`iframe-${app.name}`"
        :src="app.url"
        class="app-iframe"
        :class="{ active: app.name === activeAppName }"
        @load="onIframeLoad(app.name)"
      ></iframe>
      
      <!-- 加载动效 -->
      <div v-show="isLoading" class="loading-overlay">
        <component :is="currentLoadingComponent" />
      </div>

      <!-- 错误提示 -->
      <div v-if="showError" class="error-overlay">
        <div class="error-message">
          <div class="error-text">{{ errorMessage }}</div>
        </div>
      </div>
    </main>
  </div>
</template>

<script setup lang="ts">
import { ref, shallowRef, watch, onMounted, onUnmounted } from 'vue';
import { subApps as appConfigs, type SubAppConfig } from './apps.config';
import SpinnerLoading from './components/loading/SpinnerLoading.vue';
import DotsLoading from './components/loading/DotsLoading.vue';
import PulseLoading from './components/loading/PulseLoading.vue';
import SkeletonLoading from './components/loading/SkeletonLoading.vue';
import GradientLoading from './components/loading/GradientLoading.vue';

// 定义加载类型
const LoadingType = {
  SPINNER: 'spinner',
  DOTS: 'dots',
  PULSE: 'pulse',
  SKELETON: 'skeleton',
  GRADIENT: 'gradient'
} as const;

interface MessagePayload {
  type: 'register' | 'redirect' | 'navigate' | 'action' | 'dataset' | 'dataget' | 'data-get-response' | 'login' | 'token' | 'logout';
  payload: any;
}

type LoadingType = (typeof LoadingType)[keyof typeof LoadingType];

// 当前加载动画类型
const loadingType = ref<LoadingType>(LoadingType.DOTS);
const currentLoadingComponent = shallowRef();

// 错误提示相关
const showError = ref<boolean>(false);
const errorMessage = ref<string>('');

// Token 相关常量
const TOKEN_EXPIRY_HOURS = 8; // Token 有效期8小时
const TOKEN_CHECK_INTERVAL = 1000000; // 每分钟检查一次token
const REDIRECT_WAIT_TIME = 3000;
const LOGOUT_WAIT_TIME = 500;
const HOUR_TIME = 60 * 60 * 1000;

// 显示错误信息
const showErrorMessage = (message: string) => {
  errorMessage.value = message;
  showError.value = true;
  
  // 5秒后自动关闭错误提示
  setTimeout(() => {
    closeError();
  }, 5000);
};

// 关闭错误提示
const closeError = () => {
  showError.value = false;
  errorMessage.value = '';
};

// 根据枚举选择组件
watch(loadingType, (val) => {
  switch (val) {
    case LoadingType.SPINNER:
      currentLoadingComponent.value = SpinnerLoading;
      break;
    case LoadingType.DOTS:
      currentLoadingComponent.value = DotsLoading;
      break;
    case LoadingType.PULSE:
      currentLoadingComponent.value = PulseLoading;
      break;
    case LoadingType.SKELETON:
      currentLoadingComponent.value = SkeletonLoading;
      break;
    case LoadingType.GRADIENT:
      currentLoadingComponent.value = GradientLoading;
      break;
  }
}, { immediate: true });

interface AppInfo extends SubAppConfig {
  iframe: HTMLIFrameElement | null;
  isLoaded: boolean;
  registeredAt?: number; // 注册时间戳
}

const registeredApps = ref<Map<string, AppInfo>>(new Map());
const activeAppName = ref<string | null>(null);
const isLoading = ref<boolean>(false);
const loadingAppName = ref<string>('');
const sharedData = ref<Map<string, any>>(new Map());
const lastAppName = ref<string | null>(null);

// Token 管理相关
const token = ref<string | null>(localStorage.getItem('token'));
const tokenCreateTime = ref<number | null>(Number(localStorage.getItem('token_create_time')) || null);
let tokenCheckTimer: number | null = null;

const getOrigin = (url: string): string => {
  try {
    return new URL(url).origin;
  } catch {
    return url;
  }
};

// 检查token是否过期
const checkTokenExpiry = (): boolean => {
  if (!token.value || !tokenCreateTime.value) {
    return true; // 没有token视为过期
  }

  const currentTime = Date.now();
  const tokenAge = currentTime - tokenCreateTime.value;
  const expiryMs = TOKEN_EXPIRY_HOURS * HOUR_TIME; // 8小时转毫秒

  return tokenAge > expiryMs;
};

// 清空token并通知所有子应用
const clearTokenAndNotify = () => {
  console.info('Token已过期，正在清理...');
  
  // 清空本地存储
  token.value = null;
  tokenCreateTime.value = null;
  localStorage.clear();
  sessionStorage.clear();
  
  // 通知所有已注册的子应用清空token
  registeredApps.value.forEach((app) => {
    if (app.iframe?.contentWindow) {
      try {
        app.iframe.contentWindow.postMessage(
          {
            type: 'token-expired',
            payload: { message: 'Token已过期，请重新登录' }
          },
          getOrigin(app.url)
        );
      } catch (error) {
        console.warn(`通知应用 ${app.name} token过期失败:`, error);
      }
    }
  });
  
  // 跳转到登录页面
  redirectToLogin();
};

// 跳转到登录页面
const redirectToLogin = () => {
  const loginApp = appConfigs.find(app => app.login);
  if (loginApp) {
    // 更新登录应用的URL为登录页面
    const updatedApp: AppInfo = {
      ...loginApp,
      url: loginApp.login!,
      iframe: null,
      isLoaded: false
    };
    registeredApps.value.set(loginApp.name, updatedApp);
    
    // 激活登录应用
    activateApp(loginApp.name);
    lastAppName.value = loginApp.name;
    loadingAppName.value = loginApp.name;
    isLoading.value = true;

    setTimeout(() => {
      isLoading.value = false;
    }, LOGOUT_WAIT_TIME);
    
    console.info(`Token过期`);
  } else {
    showErrorMessage('登录已过期，请刷新页面重新登录！');
  }
};

// 设置token检查定时器
const setupTokenCheckTimer = () => {
  if (tokenCheckTimer) {
    clearInterval(tokenCheckTimer);
  }
  
  tokenCheckTimer = window.setInterval(() => {
    if (checkTokenExpiry()) {
      clearTokenAndNotify();
    }
  }, TOKEN_CHECK_INTERVAL);
};

const messageHandler = (event: MessageEvent) => {
  const { type, payload } = event.data as MessagePayload;
  const originApp = appConfigs.find(app => event.origin === getOrigin(app.url));
  if (!type) return;
  if (!originApp) return;

  switch (type) {
    case 'register':
      handleRegister(payload, event.origin);
      break;

    case 'redirect':
      handleRedirect(payload);
      break;

    case 'action':
      if (payload.action === 'toggle-fullscreen') {
        handleToggleFullScreen();
      }
      break;

    case 'logout': 
      clearTokenAndNotify();
      break;

    case 'dataset':
      const dataKey = `${payload.name}:${payload.key}`;
      sharedData.value.set(dataKey, payload.value);
      localStorage.setItem(dataKey, payload.value);
      break;

    case 'token':
      if (payload && payload.token) {
        // 存储token和创建时间
        token.value = payload.token;
        tokenCreateTime.value = Date.now();
        localStorage.setItem('token', payload.token);
        localStorage.setItem('token_create_time', tokenCreateTime.value.toString());
        if (payload.data) {
          localStorage.setItem('userdata', payload.data);
        }
        setupTokenCheckTimer(); // 重新启动token检查定时器
        onIframeLoad(appConfigs[0]?.name || '');
        initApps();
      }
      break;

    case 'dataget':
      const requestedKey = `${payload.name}:${payload.key}`;
      let value = sharedData.value.get(requestedKey);
      if (!value) {
        value = localStorage.getItem(requestedKey);
      }
      const targetIframe = registeredApps.value.get(originApp.name)?.iframe;
      if (targetIframe?.contentWindow) {
        targetIframe.contentWindow.postMessage(
          {
            type: 'data-get-response',
            payload: {
              requestId: payload.requestId,
              key: payload.key,
              value: value,
            }
          },
          getOrigin(originApp.url)
        );
      }
      break;
  }
};

// 全屏
const handleToggleFullScreen = () => {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen()
      .catch(err => console.error(`全屏失败: ${err.message}`));
  } else {
    document.exitFullscreen?.();
  }
};

// 注册
const handleRegister = (payload: { name: string; url: string }, origin: string) => {
  const { name, url } = payload;

  const iframe = document.getElementById(`iframe-${name}`) as HTMLIFrameElement | null;
  if (!iframe) {
    console.error(`注册失败，未找到 iframe: ${name}`);
    return;
  }

  const newApp: AppInfo = { 
    name, 
    url, 
    iframe, 
    isLoaded: true,
    registeredAt: Date.now() // 记录注册时间
  };
  
  registeredApps.value.set(name, newApp);
  loadingAppName.value = '';
  
  if (registeredApps.value.size === 1) {
    if (appConfigs[0]?.name === name) {
      activateApp(name);
    }
  }
};

// 跳转
const handleRedirect = (payload: { target: string; path?: string, query?: object }) => {
  const { target, path, query } = payload;
  const targetApp = registeredApps.value.get(target);

  // 新打开页面
  if (target == 'blank') {
    return window.open(path, '_blank');
  }

  // 检测跳转的服务是否注册
  if (!targetApp) {
    const errorMsg = `服务 "${target}" 尚未注册，无法进行跳转`;
    console.error(errorMsg);
    showErrorMessage(errorMsg);
    return;
  }

  // 检测当前时间和该服务的注册时间
  const currentTime = Date.now();
  const appRegisterTime = targetApp.registeredAt;
  
  if (appRegisterTime && currentTime - appRegisterTime < REDIRECT_WAIT_TIME) {
    const remainingTime = REDIRECT_WAIT_TIME - (currentTime - appRegisterTime);
    
    // 显示等待提示
    showErrorMessage(`自动跳转中，请稍等...`);
    
    // 延迟跳转
    setTimeout(() => {
      closeError(); // 关闭错误提示
      performActualRedirect(target, path, query);
    }, remainingTime);
    return;
  } else if (!appRegisterTime) {
    showErrorMessage(`服务加载中，请稍等...`);
    return;
  }

  // 立即跳转
  performActualRedirect(target, path, query);
};

// 实际执行跳转的逻辑
const performActualRedirect = (target: string, path?: string, query?: object) => {
  const targetApp = registeredApps.value.get(target);
  const lastAppName = activeAppName.value;
  const lastApp = lastAppName ? registeredApps.value.get(lastAppName) : null;

  if (!targetApp) {
    const errorMsg = `跳转失败，找不到目标应用: ${target}`;
    console.error(errorMsg);
    showErrorMessage(errorMsg);
    return;
  }

  activateApp(target);
  
  if (path && targetApp.iframe?.contentWindow) {
    targetApp.iframe.contentWindow.postMessage(
      {
        type: 'navigate',
        payload: {
          path,
          from: {
            name: lastApp?.name || '',
            url: lastApp?.url || '',
          },
          query
        }
      },
      getOrigin(targetApp.url)
    );
  }
};

// 激活应用
const activateApp = (name: string) => {
  if (!registeredApps.value.has(name)) return;
  activeAppName.value = name;
};

// iframe 加载完成
const onIframeLoad = (name: string) => {
  const iframe = document.getElementById(`iframe-${name}`) as HTMLIFrameElement | null;
  const app = registeredApps.value.get(name);
  if (app && iframe && iframe.contentWindow) {
    const firstAppConfig = appConfigs[0];
    const targetAppName = firstAppConfig?.name || '';
    const token = localStorage.getItem('token');
    if (targetAppName === name) {
      isLoading.value = false;
    }
    if (targetAppName === name && token) {
      iframe.contentWindow.postMessage(
        { type: 'token-data-init', payload: {} },
        getOrigin(app.url)
      );
    }
  }
};

// 初始化应用逻辑，处理登录跳转
const initApps = () => {
  // 检查token是否过期
  if (checkTokenExpiry() && token.value) {
    clearTokenAndNotify();
    return;
  }

  let loginUrl = '';
  let loginApp = null;
  registeredApps.value.clear(); // 清空已注册应用，重新加载
  
  appConfigs.forEach(config => { // 如果没有token，并且当前应用配置了login页面，则加载login页面
    if (!token.value && config.login) {
      loginUrl = config.login;
      loginApp = config;
      registeredApps.value.set(config.name, { ...config, url: config.login, iframe: null, isLoaded: false });
    } else {
      registeredApps.value.set(config.name, { ...config, iframe: null, isLoaded: false });
    }
  });

  if (!token.value && loginUrl && loginApp){
    activateApp((loginApp as { name: string }).name);
    lastAppName.value = (loginApp as { name: string }).name || '';
    loadingAppName.value = (loginApp as { name: string }).name || '';
    isLoading.value = true;
    return;
  }

  if (appConfigs.length > 0) {
    const firstAppConfig = appConfigs[0];
    const targetAppName = firstAppConfig?.name || '';
    activateApp(targetAppName);
    lastAppName.value = targetAppName;
    loadingAppName.value = targetAppName;
    isLoading.value = true;
    return;
  }
};

onMounted(() => {
  window.addEventListener('message', messageHandler);
  
  // 启动token检查定时器
  setupTokenCheckTimer();
  
  // 初始化时检查token是否已过期
  if (checkTokenExpiry()) {
    clearTokenAndNotify();
  } else {
    initApps(); // 调用新的初始化方法
  }
});

onUnmounted(() => {
  window.removeEventListener('message', messageHandler);
  
  // 清除定时器
  if (tokenCheckTimer) {
    clearInterval(tokenCheckTimer);
    tokenCheckTimer = null;
  }
});
</script>

<style>
body, html { margin: 0; padding: 0; width: 100vw; height: 100vh; overflow: hidden; }
.main-app { width: 100%; height: 100%; }
.app-container { width: 100%; height: 100%; }
.app-iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; opacity: 0; pointer-events: none; z-index: 1; }
.app-iframe.active { opacity: 1; pointer-events: auto; z-index: 100; }
.loading-overlay { 
  position: absolute; top: 0; left: 0; width: 100%; height: 100%; 
  background: #fff; display: flex; justify-content: center; align-items: center; 
  z-index: 999; 
}
.error-overlay {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%; 
  background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; 
  z-index: 1000;
}
.error-message {
  background: transparent; padding: 10px; border: none;
  height: 40px;
  max-width: 400px; text-align: center;
}
.error-icon {
  font-size: 20px; margin-bottom: 16px;
}
.error-text {
  font-size: 16px; color: #fefefe; margin-bottom: 5px;
}
</style>